#pragma once

#include <iostream>
#include <string>
#include "util.hpp"//使用时间戳
namespace ns_log
{
    using namespace ns_util;

     // 日志等级
    enum
    {
        INFO, //常规的
        DEBUG,//调试
        WARNING,//警告，不影响后续运行
        ERROR,
        FATAL
    };

    inline std::ostream &Log(const std::string &level, const std::string &file_name, int line)
    {
        // 添加日志等级
        std::string message = "[";
        message += level;
        message += "]";

        // 添加报错文件名称
        message += "[";
        message += file_name;
        message += "]";

        // 添加报错行
        message += "[";
        message += std::to_string(line);
        message += "]";

        // 日志时间戳
        message += "[";
        message += TimeUtil::GetTimeStamp();
        message += "]";

        // cout 本质 内部是包含缓冲区的
        std::cout << message; //不要endl进行刷新

        return std::cout;
    }

    // LOG(INFo) << "message" << "\n";//开放式日志
    // 开放式日志
    #define LOG(level) Log(#level, __FILE__, __LINE__)//#把宏参数替换成字符串

//     通过宏定义，Log() 函数得到了简化的调用形式，而内联函数 Log() 实际完成了字符串拼接和日志记录操作。这种组合提供了以下优势：

// 代码简洁：调用日志的代码简化，开发者无需每次都手动写出文件名、行号等信息。
// 高效：内联函数消除了函数调用的额外开销，特别是在频繁调用日志的情况下。
// 灵活：可以根据不同的日志级别自动生成日志，并灵活扩展日志格式（如加入时间戳、文件名等）。
// 总结
// 您在项目中使用内联函数和宏定义相结合的设计，主要是为了兼顾性能和灵活性。内联函数提高了日志的执行效率，而宏定义则简化了代码编写，并为日志级别、文件名和行号等信息的自动记录提供了方便。这种设计非常适合频繁使用的日志功能。

//     1. 内联函数的使用
// 内联函数 Log() 的作用是避免函数调用的开销，提高性能。对于日志记录这种频繁调用的操作，内联函数可以减少常规函数调用的栈操作、参数传递等开销。由于日志输出的代码比较短小，内联函数是理想的选择。内联函数的特点包括：

// 减少开销：通过直接展开函数体，避免了普通函数调用的开销。
// 性能优化：内联函数在执行时比普通函数更高效，特别是在高频调用场景中，如日志记录。
// 2. 宏定义的作用
// 宏 #define LOG(level) 结合了内联函数，使得日志功能更加灵活。通过宏定义，您可以：

// 动态传递日志级别：LOG(level) 中的 level 被 # 转换为字符串，这样日志级别如 INFO、ERROR 就会作为字符串出现在日志中，便于统一记录和格式化。
// 添加文件名和行号：__FILE__ 和 __LINE__ 是预定义的宏，宏定义让日志能够自动记录日志生成的文件名和行号。这样，无需手动输入，开发者就能追踪到日志的位置，非常方便调试。
// 简化调用：通过 LOG(level) 的方式，开发者可以轻松地记录日志，而无需手动传入日志级别、文件名、行号等，简化了代码书写。
// 3. 为什么组合内联函数和宏定义？
// 宏定义本身虽然灵活，但可能带来一些风险，如宏替换中的不安全性或难以调试的问题。而内联函数避免了这些问题，能够更安全地进行参数传递、数据操作。通过宏定义将 Log() 函数包装起来，可以使日志记录既高效又简洁，同时保留了可扩展性。

}
